﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Msdn5.Framework
{
    /// <summary>
    /// 表达式比较器
    /// 将会调用内部比较器去比较,
    /// 如果比较实体类型本身,记得重写实体类型的比较方法 !!!!!
    /// 使用方式
    /// new ExpressionComparer &lt;实体类型, 实体类型或object&gt;(x =&gt;x.属性或字段)); 
    /// </summary> 
    /// <typeparam name="T">要比较的实体类型</typeparam>
    /// <typeparam name="TKey">指定比较的属性或字段</typeparam>
    public class ExpressionComparer<T, TKey> : IComparer<T>, IEqualityComparer<T>
    {
        private readonly Func<T, TKey> _CompiledFunc; //构建比较器
        
        /// <summary>
        /// 表达式比较器
        /// 将会调用内部比较器去比较,
        /// 如果比较实体类型本身,记得重写实体类型的比较方法 !!!!!
        /// 使用方式
        /// new ExpressionComparer &lt;实体类型, 比较的属性或字段类型或object&gt;(x =&gt;x.属性或字段)); 
        /// </summary> 
        /// <typeparam name="T">要比较的实体类型</typeparam>
        /// <typeparam name="TKey">指定比较的属性或字段类型</typeparam>
        public ExpressionComparer(Expression<Func<T, TKey>> getKey)
        {
            _CompiledFunc = getKey.Compile();
        }
        public int Compare(T x, T y)
        {
            return Comparer<TKey>.Default.Compare(_CompiledFunc(x), _CompiledFunc(y));
        }
        public bool Equals(T x, T y)
        {
            //default(T) 检查 防止结构体!=null
            if (ReferenceEquals(x, default(T)) || ReferenceEquals(y, default(T))) { return false; }

            return EqualityComparer<TKey>.Default.Equals(_CompiledFunc(x), _CompiledFunc(y));
        }
        public int GetHashCode(T obj)
        {
            return EqualityComparer<TKey>.Default.GetHashCode(_CompiledFunc(obj));
        }
    }
}
